package com.xf.system.common.facade;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.xf.system.common.model.Role;
import com.xf.system.common.model.RoleMenu;
import com.xf.system.common.service.RoleMenuService;
import com.xf.system.common.service.RoleService;
import com.xf.system.common.service.UserRoleService;
import com.xf.system.enums.StatusEnum;
import com.xf.system.exception.BusinessException;
import com.xf.system.exception.Errors;
import com.xf.system.http.req.role.RoleAddReqDTO;
import com.xf.system.http.req.role.RoleChangeStatusReqDTO;
import com.xf.system.http.req.role.RoleListReqDTO;
import com.xf.system.http.req.role.RoleUpdateReqDTO;
import com.xf.system.http.vo.role.RoleDetailVO;
import com.xf.system.http.vo.role.RoleVO;
import com.xf.system.utils.StringUtil.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author xiefengf
 */
@Service
@Slf4j
public class RoleFacade {

    @Resource
    private RoleService roleService;

    @Resource
    private RoleMenuService roleMenuService;

    @Resource
    private UserRoleService userRoleService;

    /**
     * 根据条件分页查询角色列表
     *
     * @param reqDto 分页信息+查询条件
     * @return 角色分页集合信息
     */
    public RoleVO listRoles(RoleListReqDTO reqDto) {
        // 1、获取分页条件查询的数据
        IPage<RoleDetailVO> iPage = roleService.selectRoleList(reqDto);
        // 2、封装数据
        RoleVO roleVO = new RoleVO();
        List<RoleDetailVO> roleDetailVoList = iPage.getRecords().stream().peek(x -> {
            // 设置帐号状态的中文显示名称
            x.setStatusName(StatusEnum.getByName(x.getStatus()).getName());
        }).collect(Collectors.toList());
        roleVO.setRoleDetailVoList(roleDetailVoList);
        roleVO.setCurrent(iPage.getCurrent());
        roleVO.setSize(iPage.getSize());
        roleVO.setPages(iPage.getPages());
        roleVO.setTotal(iPage.getTotal());
        // 3、返回数据
        return roleVO;
    }

    /**
     * 通过角色id查询角色详情信息
     *
     * @param id 角色id
     * @return 角色详情信息
     */
    public RoleDetailVO getRoleById(Long id) {
        // 1、查询当前角色信息
        RoleDetailVO roleDetailVo = roleService.selectRoleByRid(id);
        // 设置帐号状态的中文显示名称
        roleDetailVo.setStatusName(StatusEnum.getByName(roleDetailVo.getStatus()).getName());
        // 2、返回数据
        return roleDetailVo;
    }

    /**
     * 新增角色信息
     *
     * @param reqDto 角色信息
     * @return 执行结果
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveRole(RoleAddReqDTO reqDto) {
        // 1、校验数据 角色名称/角色权限字符串 在数据库中唯一
        // 1.1 校验角色名称在数据库中唯一
        Role roleByRoleName = roleService.selectRoleByRoleName(reqDto.getRoleName());
        if (StringUtils.isNotNull(roleByRoleName)){
            // 角色名称已存在
            throw new BusinessException(Errors.System.SYSTEM_01013);
        }
        // 1.2 校验角色权限字符串在数据库中唯一
        Role roleByRoleKey = roleService.selectRoleByRoleKey(reqDto.getRoleKey());
        if (StringUtils.isNotNull(roleByRoleKey)){
            // 角色权限字符串已存在
            throw new BusinessException(Errors.System.SYSTEM_01014);
        }
        // 2、保存角色数据
        Role role = new Role();
        BeanUtils.copyProperties(reqDto,role);
        boolean saveRole = roleService.save(role);
        boolean saveRoleMenu = Boolean.TRUE;
        Long id = role.getId();
        // 3、保存角色-菜单关联信息
        if (!CollectionUtils.isEmpty(reqDto.getMenuIdList())){
            List<RoleMenu> menuList = new ArrayList<>();
            for (Long menuId : reqDto.getMenuIdList()) {
                RoleMenu roleMenu = new RoleMenu(id,menuId);
                menuList.add(roleMenu);
            }
            saveRoleMenu = roleMenuService.saveBatch(menuList);
        }
        // 4、返回执行结果
        return saveRole && saveRoleMenu;
    }

    /**
     * 更新角色信息
     *
     * @param reqDto 角色信息
     * @return 执行结果
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateRole(RoleUpdateReqDTO reqDto) {
        // 角色id
        Long id = reqDto.getId();
        // 1、校验数据 角色名称/角色权限字符串 在数据库中唯一
        // 1.1 校验角色名称在数据库中唯一，且不是当前角色
        Role roleByRoleName = roleService.selectRoleByRoleName(reqDto.getRoleName());
        if (StringUtils.isNotNull(roleByRoleName) && !id.equals(roleByRoleName.getId())){
            // 角色名称已存在
            throw new BusinessException(Errors.System.SYSTEM_01013);
        }
        // 1.2 校验角色权限字符串在数据库中唯一，且不是当前角色
        Role roleByRoleKey = roleService.selectRoleByRoleKey(reqDto.getRoleKey());
        if (StringUtils.isNotNull(roleByRoleKey) && !id.equals(roleByRoleKey.getId())){
            // 角色权限字符串已存在
            throw new BusinessException(Errors.System.SYSTEM_01014);
        }
        // 2、更新角色信息
        Role role = new Role();
        BeanUtils.copyProperties(reqDto,role);
        boolean updateRole = roleService.updateById(role);
        boolean updateRoleMenu = Boolean.TRUE;
        // 3、更新角色-菜单关联信息（先删再新增）
        if (!CollectionUtils.isEmpty(reqDto.getMenuIdList())){
            // 删除角色与菜单关联
            roleMenuService.deleteRoleMenuByRid(id);
            // 新增角色与菜单关联
            List<RoleMenu> menuList = new ArrayList<>();
            for (Long menuId : reqDto.getMenuIdList()) {
                RoleMenu roleMenu = new RoleMenu(id,menuId);
                menuList.add(roleMenu);
            }
            updateRoleMenu = roleMenuService.saveBatch(menuList);
        }
        // 4、返回执行结果
        return updateRole && updateRoleMenu;
    }

    /**
     * 批量删除角色信息
     *
     * @param idList 角色id列表
     * @return 执行结果
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteRole(Long[] idList) {
        // 1、校验数据 角色还有对应的用户，不能删除
        List<Long> roleIdList = Arrays.stream(idList).collect(Collectors.toList());
        Integer count = userRoleService.countUserRoleByRid(roleIdList);
        if (count > 0){
            throw new BusinessException(Errors.System.SYSTEM_01015);
        }
        // 2、删除角色与菜单关联
        roleMenuService.deleteRoleMenuByRidList(roleIdList);
        // 3、删除角色信息+返回执行结果
        return roleService.removeByIds(roleIdList);
    }

    /**
     * 角色状态修改
     *
     * @param reqDto 角色id+角色状态
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean changeStatus(RoleChangeStatusReqDTO reqDto) {
        // 1、根据角色id查询角色信息
        Role role = roleService.getById(reqDto.getId());
        if (StringUtils.isNull(role)){
            // 当前角色不存在
            throw new BusinessException(Errors.System.SYSTEM_01016);
        }
        // 2、更新密码
        role.setStatus(reqDto.getStatus());
        return roleService.updateById(role);
    }


}
